package cn.pacerx.running.wx.task;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.List;

import cn.pacerx.running.core.system.SystemConfig;
import cn.pacerx.running.core.task.TaskService;
import cn.pacerx.running.db.domain.Activity;
import cn.pacerx.running.db.domain.RunningOrder;
import cn.pacerx.running.db.enums.ActivityStatusEnum;
import cn.pacerx.running.db.service.RunningOrderService;
import cn.pacerx.running.wx.service.ActivityService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class TaskStartupRunner implements ApplicationRunner {

    @Autowired
    private RunningOrderService orderService;
    @Autowired
    private TaskService taskService;

    private final ActivityService activityService;

    @Override
    public void run(ApplicationArguments args) {
        initUnpaidOrder();
        initActivityExpired();
    }

    private void initActivityExpired() {
        List<Activity> activityList = activityService.getValidList();
        LocalTime startTime = LocalTime.of(0, 0, 0);
        LocalTime endTime = LocalTime.of(23, 59, 59);
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime firstDateTime = LocalDate.now().atTime(startTime);

        for (Activity activity : activityList) {
            LocalDate endDate = activity.getEndDate();
            LocalDateTime endDateTime = LocalDateTime.of(endDate, endTime);
            if (endDateTime.isBefore(now)) {
                // 已经过期，则加入延迟队列
                taskService.addTask(new ActivityExpiredTask(activity.getId(), 0));
                continue;
            }
            // 还没过期，则加入延迟队列
            long delay = ChronoUnit.MILLIS.between(now, endDateTime);
            taskService.addTask(new ActivityExpiredTask(activity.getId(), delay));
            // 活动锁定
            if (activity.getStatus() == ActivityStatusEnum.PENDING) {
                endDateTime = activity.getStartDate().minusDays(1L).atTime(startTime);
                if (endDateTime.isBefore(now)) {
                    taskService.addTask(new ActivityLockedTask(activity.getId(), 0));
                } else {
                    delay = ChronoUnit.MILLIS.between(now, endDateTime);
                    taskService.addTask(new ActivityLockedTask(activity.getId(), delay));
                }
                // 进行中
                endDateTime = activity.getStartDate().atTime(startTime);
                delay = ChronoUnit.MILLIS.between(firstDateTime, endDateTime);
                taskService.addTask(new ActivityProgressingTask(activity.getId(), delay));
            }
            // 进行中
            if (activity.getStatus() == ActivityStatusEnum.LOCKED) {
                if (activity.getStartDate().isEqual(now.toLocalDate())) {
                    taskService.addTask(new ActivityProgressingTask(activity.getId(), 0));
                } else {
                    endDateTime = activity.getStartDate().atTime(startTime);
                    delay = ChronoUnit.MILLIS.between(firstDateTime, endDateTime);
                    taskService.addTask(new ActivityProgressingTask(activity.getId(), delay));
                }
            }
        }
    }

    private void initUnpaidOrder() {
        List<RunningOrder> orderList = orderService.queryUnpaid(SystemConfig.getOrderUnpaid());
        for (RunningOrder order : orderList) {
            LocalDateTime add = order.getAddTime();
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime expire = add.plusMinutes(SystemConfig.getOrderUnpaid());
            if (expire.isBefore(now)) {
                // 已经过期，则加入延迟队列
                taskService.addTask(new OrderUnpaidTask(order.getId(), 0));
            } else {
                // 还没过期，则加入延迟队列
                long delay = ChronoUnit.MILLIS.between(now, expire);
                taskService.addTask(new OrderUnpaidTask(order.getId(), delay));
            }
        }
    }
}